#define _STR_MODULE_
#include "osObjects.h"
#include "strctr.h"
#include "ff.h"
#include "stdio.h"
#include "com_hal.h"
#include "sdcard.h"	


sd_error_enum sd_io_init(void);

FRESULT open_append (FIL* fp,const char* path);

union { 
    uint8_t bytes[1024];
    uint16_t words[512];
    uint32_t dwords[256];
} Gd25DataBuff;

FRESULT FsSt;
FATFS Sdfs;
FIL fil;

sd_error_enum SdSt;
sd_card_info_struct sd_cardinfo;

/*!
    \brief      configure the NVIC
    \param[in]  none
    \param[out] none
    \retval     none
*/
void nvic_config(void)
{
    //nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
    nvic_irq_enable(SDIO_IRQn, 0, 0);
}

/*****************************************************************************//*!
*
* @brief   led task.
*     
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/

void StrCtrTask(void const *argument) {
    uint16_t Cnt;

   // gdSpiInit();
    Cnt = 0;
    osDelay(1000);
    
    nvic_config();
    
    if(FR_OK == FsSt){
        Cnt = 1;
    }   
    
    Cnt = 5;
    SdSt = SD_ERROR;
    while((Cnt--) && (SD_OK != SdSt )){
        SdSt = sd_io_init();
    }
    
    if(SD_OK == SdSt){
        SdSt = sd_block_read(Gd25DataBuff.dwords , 0, 512);
    }
    osDelay(500);
    
    if(SD_OK == SdSt){
        //SD_GetCardInfo(&SdInfo);
        //SD_ReadWaitOperation();
        //SD_GetStatus();
        //SdSt = SD_ReadBlock(Gd25DataBuff.bytes, 0, 512);
    }
    
    if(SD_OK == SdSt){
   
    }
    
    FsSt = f_mount(&Sdfs,"",0);
    open_append(&fil,"app.c");

    for (;;) {
        
        osDelay(5000);
        
        osMutexWait ( mid_StrMutex, 0);
        //gd25qRead(Cnt, 1024, Gd25DataBuff);
        osMutexRelease (mid_StrMutex);
        
        Cnt++;
        if(Gd25DataBuff.bytes[0]){
           // Cnt = 256;
            //while(Cnt--)
            //  Gd25DataBuff[Cnt] = Cnt;
            //gd25qWrite(0x00, 256, Gd25DataBuff);
            //gd25qWrite(0x100, 256, Gd25DataBuff);
            //gd25qWrite(0x200, 256, Gd25DataBuff);
            //gd25qWrite(0x300, 256, Gd25DataBuff);
            //gd25qWrite(0x400, 256, Gd25DataBuff);
            //gd25qWrite(0x500, 256, Gd25DataBuff);
        }
    }
}

/*****************************************************************************//*!
*
* @brief   led task.
*     
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
FRESULT open_append (
    FIL* fp,            /* [OUT] File object to create */
    const char* path    /* [IN]  File name to be opened */
)
{
    FRESULT fr;
    UINT FsResdLen;
    FRESULT FsSt;

    /* Opens an existing file. If not exist, creates a new file. */
    fr = f_open(fp, path, FA_READ | FA_WRITE | FA_OPEN_ALWAYS);
    if (fr == FR_OK) {
        /* Seek to end of the file to append data */
        fr = f_read(&fil, Gd25DataBuff.bytes, 1000, &FsResdLen);
        if (fr != FR_OK){
            f_close(fp);
            return fr;
        }
        
        fr = f_lseek(fp, f_size(fp)-512);
        if (fr != FR_OK)
            f_close(fp);
    }
    
    FsSt = fr;
    
    if (FsSt == FR_OK) {
        FsSt = f_read(&fil, &Gd25DataBuff.bytes[1000], 1000, &FsResdLen);
        f_close(&fil);
    }
    
    FsSt = f_open(&fil, "app.c", FA_READ | FA_WRITE | FA_OPEN_ALWAYS);
    if(FR_OK == FsSt){
        for(;;){
            FsSt = f_read(&fil, &Gd25DataBuff.bytes[0], 128, &FsResdLen);
            if(FR_OK == FsSt){
                Gd25DataBuff.bytes[FsResdLen] = 0;
                printf((char const*)Gd25DataBuff.bytes);
                osDelay(10);
                while(!ComTxStCheck()){osDelay(5);}
                if(128 > FsResdLen){
                    break;
                }
            }
        }
        f_close(&fil);
    }
    
    return fr;
}


sd_error_enum sd_io_init(void)
{
    sd_error_enum status = SD_OK;
    uint32_t cardstate = 0;
    status = sd_init();
    if(SD_OK == status){
        status = sd_card_information_get(&sd_cardinfo);
    }
    if(SD_OK == status){
        status = sd_card_select_deselect(sd_cardinfo.card_rca);
    }
    status = sd_cardstatus_get(&cardstate);
    if(cardstate & 0x02000000){
        printf("\r\n the card is locked!");
        while (1){
        }
    }
    if ((SD_OK == status) && (!(cardstate & 0x02000000)))
    {
        /* set bus mode */
        status = sd_bus_mode_config(SDIO_BUSMODE_4BIT);
//        status = sd_bus_mode_config( SDIO_BUSMODE_1BIT );
    }
    if (SD_OK == status)
    {
        /* set data transfer mode */
//        status = sd_transfer_mode_config( SD_DMA_MODE );
        status = sd_transfer_mode_config( SD_POLLING_MODE );
    }
    return status;
}
